/*
 * processmgt.cpp
 *
 *  Created on: 2011-5-25
 *      Author: chenl
 */

#include "processmgt.h"
#include "os/sched.h"
#include "common/common_err.h"
#include "task_wrapper.h"
#include "taskqueue.h"
#include "priorunqueue.h"
#include "tasklist.h"
#include "config.h"
#include "global.h"

#define DEFAULT_PROCESSMGT_LOGPREFIX	"./log/psmgt"

CProcessMgt::CProcessMgt() :
	logEngine(DEFAULT_PROCESSMGT_LOGPREFIX, LOGLEVEL),
	pRunQueue(NULL), pWaitQueue(NULL), pTaskHashList(NULL),
	init_(0),  pRoot_(0), current_(0)
{

}

CProcessMgt::~CProcessMgt()
{

}

int32_t CProcessMgt::Initialize()
{
	const CParamConfig& config = GET_PARAMCONFIG_INSTANCE();
	switch (config.GetScheduler())
	{
	case enmScheduler_O_N:
		pRunQueue = new CTaskQueue();
		break;
	case enmScheduler_O_1:
		pRunQueue = new CPrioRunQueue();
		break;
	case enmScheduler_BFS:
	case enmScheduler_CFS:
	default:
		return E_PS_MISCONFIGED;
	}
	if (NULL == pRunQueue)
	{
		return E_PS_INIT_RUNQUEUE_FAIL;
	}
	pWaitQueue = new CTaskQueue();
	if (NULL == pWaitQueue)
	{
		delete pRunQueue;
		return E_PS_INIT_WAITQUEUE_FAIL;
	}
	pTaskHashList = new CTaskHashList();
	if (NULL == pTaskHashList)
	{
		delete pRunQueue;
		delete pWaitQueue;
		return E_PS_INIT_HASHLIST_FAIL;
	}

	init_ = &CTask::InitTask();
	pRoot_ = init_;
	current_ = init_;
	return S_OK;
}

int32_t CProcessMgt::Uninitialize()
{
	delete pRunQueue;
	delete pWaitQueue;
	delete pTaskHashList;
	return S_OK;
}

int32_t CProcessMgt::NewTask(CTask& oldTask, CTask& newTask)
{
	struct task_struct *p = &oldTask.task;
	struct task_struct *q = &newTask.task;

	logEngine.WriteLog(enmLogLevel_DEBUG,
				"fork... father=%d, child=%d", p->pid, q->pid);

	if(NULL != p->p_cptr)
	{
		p->p_cptr->p_ysptr = q;
	}
	q->p_osptr = p->p_cptr;
	q->p_pptr = q->p_opptr = p;
	p->p_cptr = q;

	InsertTaskToHashList(newTask);

	return S_OK;
}

int32_t CProcessMgt::DeleteTask(CTask& task)
{
	int32_t ret = S_OK;
	struct task_struct* p = &task.task;
	if (IsTaskOnRunQueue(task))
	{
		logEngine.WriteLog(enmLogLevel_DEBUG,
				"Deleting Task(pid=%d), task is in runqueue!", p->pid);
		ret = DelTaskFromRunqueue(task);
		if (0 > ret)
		{
			logEngine.WriteLog(enmLogLevel_WARN,
					"Delete task(pid=%d) in runqueue failed", p->pid);
			ret = E_PS_DELETETASKFAIL;
		}
	}
	if (IsTaskOnWaitQueue(task))
	{
		logEngine.WriteLog(enmLogLevel_DEBUG,
				"Deleting Task(pid=%d), task is in waitqueue!", p->pid);
		ret = DelTaskFromWaitQueue(task);
		if (0 > ret)
		{
			logEngine.WriteLog(enmLogLevel_WARN,
					"Delete task(pid=%d) in waitqueue failed", p->pid);
			ret = E_PS_DELETETASKFAIL;
		}
	}
	if (IsTaskOnHashList(p->pid))
	{
		logEngine.WriteLog(enmLogLevel_DEBUG,
				"Deleting Task(pid=%d), task is in hashlist!", p->pid);
		ret = DelTaskFromHashList(p->pid);
		if (0 > ret)
		{
			logEngine.WriteLog(enmLogLevel_WARN,
					"Delete task(pid=%d) in hashlist failed", p->pid);
			ret = E_PS_DELETETASKFAIL;
		}
	}
	ret = DelTaskFromProcessTree(task);
	if (0 > ret)
	{
		logEngine.WriteLog(enmLogLevel_WARN,
				"Delete task(pid=%d) in process tree failed", p->pid);
	}
	return ret;
}

int32_t CProcessMgt::DeleteTask(pid_t pid)
{
	CTask* pTask = GetTaskByPid(pid);
	if (unlikely(NULL == pTask))
	{
		return E_PS_HASHLIST_CLOBBERED;
	}
	return DeleteTask(*pTask);
}



int32_t CProcessMgt::DelTaskFromProcessTree(CTask& task)
{
	struct task_struct* p = &task.task;
	//Make init inherit all the child processes
	while(NULL != p->p_cptr)
	{
		struct task_struct* tmp = p->p_cptr;

		p = p->p_osptr;
		tmp->p_ysptr = NULL;
		tmp->p_pptr = tmp->p_opptr;
		if (NULL != tmp->p_osptr)
		{
			tmp->p_osptr->p_ysptr = tmp;
		}
		tmp->p_pptr->p_cptr = tmp;
	}
	return S_OK;
}







